using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Mail;
using System.Data;
using System.IO;

namespace LicenseGenerator
{
    public class util
    {
        private static string quote = "\"";
        private static string lb = System.Environment.NewLine;

        public util()
        {
        }

        #region Software License
        /// <summary>
        /// generate a unique key for license given user, company & number of license
        /// tested
        /// </summary>
        /// <param name="username"></param>
        /// <param name="company"></param>
        /// <param name="num_of_license"></param>
        /// <returns></returns>
        public static string GenerateKeyForInformation(string username, string company, string num_of_license)
        {
            string key = "";

            string pattern = "USER=%USER%+COMPANY=%COMPANY%+LICENSE_NO=%LICENSE_NO%";
            pattern = pattern.Replace("%USER%", username).Replace("%COMPANY%", company).Replace("%LICENSE_NO%", num_of_license);

            key = EncryptString(pattern, def.salt_string);
            key = EncryptString(key, def.salt_string_two);

            return key;
        }

        /// <summary>
        /// check if a given key is valid for the supplied user information
        /// tested
        /// </summary>
        /// <param name="username"></param>
        /// <param name="company"></param>
        /// <param name="num_of_license"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool IfKeyIsValid(string username, string company, string num_of_license, string key)
        {
            string pattern = "USER=%USER%+COMPANY=%COMPANY%+LICENSE_NO=%LICENSE_NO%";
            pattern = pattern.Replace("%USER%", username).Replace("%COMPANY%", company).Replace("%LICENSE_NO%", num_of_license);

            string DecryptedKey = DecryptString(key, def.salt_string_two);
            DecryptedKey = DecryptString(DecryptedKey, def.salt_string);

            if (DecryptedKey == pattern)
                return true;
            else
                return false;
        }
        #endregion //Software License

        #region String Functions
        /// <summary>
        /// turn a key=value hash into a string like: key1=value1;key2=value2 string
        /// </summary>
        /// <param name="ht"></param>
        /// <returns></returns>
        public static string TurnHashIntoString(System.Collections.Hashtable ht)
        {
            string sep = ";";

            string res = "";
            if (ht.Count > 0)
            {
                foreach (string key in ht.Keys)
                {
                    string value = ht[key].ToString();

                    if (string.IsNullOrEmpty(res))
                    {
                        res = key + "=" + value;
                    }
                    else
                    {
                        res += sep + key + "=" + value;
                    }
                }
            }

            return res;
        }

        /// <summary>
        /// turn a string like: key1=value1;key2=value2 into a hash of key=value
        /// tested
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static System.Collections.Hashtable TurnStringIntoHash(string str)
        {
            string sep = ";";
            System.Collections.Hashtable ht = new System.Collections.Hashtable();
            if (str.Trim() != "")
            {
                string[] pairs = str.Split(new char[] {char.Parse(sep) });
                foreach (string pair in pairs)
                {
                    string[] keyvaluepair = pair.Split(new char[] { '=' });

                    string key = keyvaluepair[0];
                    string value = keyvaluepair[1];
                    ht[key] = value;
                }
            }

            return ht;
        }

        /// <summary>
        /// take a hash table of key = value and turn it into string by replacing %key% with ht[key] value
        /// tested
        /// </summary>
        /// <param name="ht"></param>
        /// <param name="pattern"></param>
        /// <returns></returns>
        public static string PutHashInPattern(System.Collections.Hashtable ht, string pattern)
        {
            string res = pattern;

            foreach (string key in ht.Keys)
            {
                string substr = "%" + key + "%";
                string subval = ht[key].ToString().Trim();

                res = res.Replace(substr, subval);
            }

            return res;
        }
        #endregion //String Functions

        #region File Functions
        #region Byte Array
        /// <summary>
        /// read the content of a binary file into a byte array
        /// </summary>
        /// <param name="filename">input file name</param>
        /// <returns>byte array contains the binary data</returns>
        public static byte[] ReadFileIntoByteArray(string filename)
        {
            byte[] data = null;
            try
            {
                System.IO.FileInfo fi = new System.IO.FileInfo(filename);
                long numBytes = fi.Length;

                System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read);

                System.IO.BinaryReader br = new System.IO.BinaryReader(fs);

                data = br.ReadBytes((int)numBytes);

                br.Close();

                fs.Close();
            }
            catch (System.Exception)
            {
            }

            return data;
        }

        /// <summary>
        /// take byte array and turn it into bitmap image
        /// </summary>
        /// <param name="imagebyte"></param>
        /// <returns></returns>
        public static System.Drawing.Bitmap SaveByteArrayIntoBitMap(byte[] imagebyte)
        {
            MemoryStream stream = new MemoryStream(imagebyte);
            System.Drawing.Bitmap image = new System.Drawing.Bitmap(stream);
            return image;
        }

        /// <summary>
        /// Writes the content of byte array into a file
        /// </summary>
        /// <param name="data">byte array contains data</param>
        /// <param name="filename">output file name</param>
        public static void WriteByteArrayToFile(byte[] data, string filename)
        {
            try
            {
                System.IO.BinaryWriter bw = new System.IO.BinaryWriter(System.IO.File.Open(filename, System.IO.FileMode.Create));

                bw.Write(data);

                bw.Close();
            }
            catch (System.Exception ex)
            {
                HandleException(ex);
            }
        }
        #endregion //Byte Array

        #region Misc File Functions

        public static string ReadTextFileIntoString(string sFileName)
        {
            string output = "";
            if (System.IO.File.Exists(sFileName))
            {
                System.IO.StreamReader sr = new System.IO.StreamReader(sFileName);

                output = sr.ReadToEnd();

                sr.Close();
            }
            return output;
        }

        public static void WriteTextFile(string sLogFileName, string sMessageLine)
        {
            System.IO.FileStream fs = new System.IO.FileStream(sLogFileName, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
            System.IO.StreamWriter m_streamWriter = new System.IO.StreamWriter(fs);
            m_streamWriter.BaseStream.Seek(0, System.IO.SeekOrigin.End);
            m_streamWriter.WriteLine(sMessageLine);
            m_streamWriter.Flush();
            m_streamWriter.Close();
        }

        /// <summary>
        /// generates a random file name consist of today's date, time, and a random number
        /// </summary>
        /// <returns></returns>
        public static string GenerateRandomFileName()
        {
            string filename = "";

            System.Random rn = new System.Random();

            System.DateTime dt = System.DateTime.Now;

            //the random file name is in the format of
            //2008050212584012345
            //<YYYY><MM><DD><HH><MM><SS><5digit random number>
            filename = dt.Year.ToString() + dt.Month.ToString().PadLeft(2, '0') + dt.Day.ToString().PadLeft(2, '0') + dt.Hour.ToString().PadLeft(2, '0') + dt.Minute.ToString().PadLeft(2, '0') + dt.Second.ToString().PadLeft(2, '0');

            filename += rn.Next(10000, 99999).ToString();

            return filename;
        }

        #endregion // Misc File Functions

        #region Serialization

        /// <summary>
        /// Serialize a object to file
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="filename"></param>
        public static void serializeObject(System.Object obj, string filename)
        {
            try
            {
                System.Runtime.Serialization.IFormatter ft = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();

                System.IO.Stream st = new System.IO.FileStream(filename, System.IO.FileMode.Create, System.IO.FileAccess.Write, System.IO.FileShare.None);

                ft.Serialize(st, obj);
                st.Close();
            }
            catch (System.Exception ex)
            {
                HandleException(ex);
            }
        }

        /// <summary>
        /// Deserialize a file into object
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static System.Object DeserializeObject(string filename)
        {
            System.Object obj = null;
            try
            {
                System.Runtime.Serialization.IFormatter ft = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
                System.IO.Stream st = new System.IO.FileStream(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);
                obj = ft.Deserialize(st);
                st.Close();
            }
            catch (System.Exception ex)
            {
                HandleException(ex);
            }

            return obj;
        }
        #endregion //Serialization

        #endregion // File Functions

        #region System Functions
        /// <summary>
        /// Launch a file
        /// </summary>
        /// <param name="filename">filename or program exe name</param>
        public static void RunFile(string filename)
        {
            System.Diagnostics.Process.Start(@filename);
        }

        public static void RunFileWaitForExit(string filename)
        {
            System.Diagnostics.Process ps = new System.Diagnostics.Process();

            if (filename.IndexOf(" ") > -1)
            {
                ps.StartInfo.FileName = @filename;
            }
            else
            {
                ps.StartInfo.FileName = filename;
            }

            ps.Start();

            ps.WaitForExit();
            ps.Close();
        }
        #endregion //System Functions

        #region User Interface
        /// <summary>
        /// get a random image file from a path of image files
        /// </summary>
        /// <param name="path"></param>
        /// <param name="PreviousFileName"></param>
        /// <returns></returns>
        public static string GetRandomImageFile(string path, string PreviousFileName)
        {
            string ImageFileName = "";
            string[] filelist = System.IO.Directory.GetFiles(path);

            if (filelist.Length > 0)
            {
                List<string> list = new List<string>();
                list.AddRange(filelist);

                int prevIndex = list.IndexOf(PreviousFileName);

                int index = -1;

                Random ra = new Random();
                
                index = ra.Next(0, filelist.Length - 1);

                if (index != prevIndex)
                    ImageFileName = filelist[index];
                else
                    ImageFileName = GetRandomImageFile(path, PreviousFileName);
            }

            return ImageFileName;
        }

        /// <summary>
        /// setup a como box, populate with data table, and adds a blank field
        /// </summary>
        /// <param name="cbo">Combo Box name</param>
        /// <param name="dt">DataTable contains the values</param>
        /// <param name="valuefield">Value Field</param>
        /// <param name="displayfield">Display Field</param>
        public static void SetupCombo(System.Windows.Forms.ComboBox cbo, System.Data.DataTable dt, string group)
        {
            string displayfield = "DESC";
            string valuefield = "CODE";

            System.Data.DataTable temp = new System.Data.DataTable();
            temp.Columns.Add(displayfield);
            temp.Columns.Add(valuefield);
            System.Data.DataRow ar = null;
            ar = temp.NewRow();
            ar[displayfield] = "";
            ar[valuefield] = 0;
            temp.Rows.Add(ar);

            DataRow[] dlist = dt.Select("[CODE_GROUP] = '" + group + "'");
            foreach (System.Data.DataRow nr in dlist)
            {
                ar = temp.NewRow();
                ar[displayfield] = nr[displayfield];
                ar[valuefield] = nr[valuefield];
                temp.Rows.Add(ar);
            }

            cbo.DataSource = temp;
            cbo.DisplayMember = displayfield;
            cbo.ValueMember = valuefield;
            cbo.SelectedValue = 0;
        }
        #endregion //User Interface

        #region Database
        private static string ProcessValueDataTableToThermo(string val)
        {
            string res = val;
            
            res = res.Replace("\'", "''"); //replace apostrophy w/ 2 single quotes to construct a valid sql statement

            switch (res.ToUpper().Trim())
            {
                case "T":
                    res = "TRUE";
                    break;
                case "F":
                    res = "FALSE";
                    break;
                default:
                    break;
            }

            return quote + res + quote;
        }

        public static DataTable ThermoCSVFileToDataTable(string filename)
        {
            System.Data.DataTable dt = new DataTable();

            try
            {
                System.DateTime starttime = System.DateTime.Now;

                string table = "[" + System.IO.Path.GetFileNameWithoutExtension(filename) + "]";

                string tablename = "", list_field_name = "", list_field_length = "", record_count = "";

                using (StreamReader sr = new StreamReader(filename))
                {
                    string aline = "";
                    int ln = 1;
                    int record_process_count = 0;

                    while ((aline = sr.ReadLine()) != null)
                    {
                        aline = aline.Trim();

                        switch (ln)
                        {
                            case 1:
                                tablename = aline;
                                dt.TableName = tablename.Trim().ToUpper();
                                break;
                            case 2:
                                list_field_name = aline;
                                break;
                            case 3:
                                list_field_length = aline;

                                //Create table fields
                                string[] fieldlist = list_field_name.Split(new char[] { ',' });
                                string[] fieldlength = list_field_length.Split(new char[] { ',' });
                                for (int i = 0; i < fieldlist.Length; i++)
                                {
                                    string afield = fieldlist[i].ToString().Trim();
                                    int afieldlength = Int32.Parse(fieldlength[i].Trim());

                                    DataColumn dc = new DataColumn(afield);
                                    dc.MaxLength = afieldlength;

                                    dt.Columns.Add(dc);
                                }
                                break;
                            case 4:
                                record_count = aline;
                                break;
                            default:
                                InsertDataLine(aline, dt);
                                record_process_count++;
                                break;
                        }
                        ln++;
                    }

                    System.DateTime stopTime = System.DateTime.Now;

                    System.TimeSpan ts = stopTime - starttime;
                }
            }
            catch (System.Exception ex)
            {
                HandleException(ex);
            }

            return dt;
        }

        private static void InsertDataLine(string line, System.Data.DataTable dt)
        {
            System.Data.DataRow nr = dt.NewRow();

            line = line.Replace("\",", "\"!"); //replace ", with something distinguish ", --> "! in order to separate values in the case where there is comma inside the value

            string[] values = line.Split(new char[] { '!' });
            for (int i = 0; i < values.Length; i++)
            {
                nr[i] = ProcessValueThermoCSV(values[i].ToString().Trim());
            }

            dt.Rows.Add(nr);
        }

        private static string ProcessValueThermoCSV(string val)
        {
            string quote = "\"";

            string res = val.Replace(quote, "");

            switch (res.ToUpper().Trim())
            {
                case "TRUE":
                    res = "T";
                    break;
                case "FALSE":
                    res = "F";
                    break;
                default:
                    break;
            }

            return res;
        }

        public static DataTable DataListToDataTable(System.Collections.ArrayList DataList, string TableName)
        {
            System.Data.DataTable dt = new DataTable(TableName);

            if (DataList.Count > 0)
            {
                for (int i = 0; i < DataList.Count; i++)
                {
                    if (DataList[i] is List<string>)
                    {
                        List<string> line = (List<string>)DataList[i];
                        
                        //define columns
                        if (i == 0)
                        {
                            foreach (string aField in line)
                            {
                                dt.Columns.Add(new DataColumn(aField));
                            }
                        }
                        else
                        {
                            DataRow nr = dt.NewRow();

                            for (int j = 0; j < line.Count; j++)
                            {
                                string value = line[j].Trim();

                                if (value != "")
                                    nr[j] = value;
                                else
                                    nr[j] = System.DBNull.Value;
                            }

                            dt.Rows.Add(nr);
                        }
                    }
                } //EO For 
            }

            return dt;
        }

        public static void DataTableToThermoCSVFile(System.Data.DataTable dt, string filename)
        {
            int RecordLimit = 5000;
            try
            {
                if (dt.Rows.Count > 0)
                {
                    if (dt.Rows.Count < RecordLimit)
                    {
                        DataTableToThermoCSVFile_WriteOneString(dt, filename);
                    }
                    else
                    {
                        DataTableToThermoCSVFile_WriteLineByLine(dt, filename);
                    }
                }
            }
            catch (System.Exception ex)
            {
                HandleException(ex);
            }
        }

        public static void DataTableToThermoCSVFile_WriteLineByLine(System.Data.DataTable dt, string filename)
        {
            string tablename = "temp", field_name_list = "", field_length_list = "";

            if (dt.TableName != "")
                tablename = dt.TableName;

            System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
            System.IO.StreamWriter sw = new System.IO.StreamWriter(fs);

            sw.WriteLine(tablename);

            foreach (DataColumn dc in dt.Columns)
            {
                string fieldname = dc.ColumnName.Trim();
                string fieldlength = dc.MaxLength.ToString();

                field_name_list = AddItemToList(field_name_list, fieldname);
                //Thermo Samplemanager table loader would be able to load data correctly if put all 0s for field length, it's only for checking purpose
                field_length_list = AddItemToList(field_length_list, "0");
            }

            sw.WriteLine(field_name_list);
            sw.WriteLine(field_length_list);
            sw.WriteLine(dt.Rows.Count.ToString().Trim());

            //output data
            foreach (DataRow dr in dt.Rows)
            {
                string valuelist = "";
                foreach (DataColumn dc in dt.Columns)
                {
                    string value = ("" + dr[dc.ColumnName]).Trim();
                    valuelist = AddItemToList(valuelist, ProcessValueDataTableToThermo(value));
                }

                sw.WriteLine(valuelist);
            }

            sw.Flush();
            sw.Close();
        }

        public static void DataTableToThermoCSVFile_WriteOneString(System.Data.DataTable dt, string filename)
        {
            string output = "";

            string tablename = "temp", field_name_list = "", field_length_list = "";

            if (dt.TableName != "")
                tablename = dt.TableName;

            output += tablename + lb;

            foreach (DataColumn dc in dt.Columns)
            {
                string fieldname = dc.ColumnName.Trim();
                string fieldlength = dc.MaxLength.ToString();

                field_name_list = AddItemToList(field_name_list, fieldname);
                //Thermo Samplemanager table loader would be able to load data correctly if put all 0s for field length, it's only for checking purpose
                field_length_list = AddItemToList(field_length_list, "0");
            }

            output += field_name_list + lb;
            output += field_length_list + lb;
            output += dt.Rows.Count.ToString().Trim() + lb;

            //output data
            string value_data = "";
            foreach (DataRow dr in dt.Rows)
            {
                string valuelist = "";
                foreach (DataColumn dc in dt.Columns)
                {
                    string value = ("" + dr[dc.ColumnName]).Trim();
                    valuelist = AddItemToList(valuelist, ProcessValueDataTableToThermo(value));
                }
                value_data += valuelist + lb;
            }

            output += value_data;
            WriteTextFile(filename, output);
        }
        
        /// <summary>
        /// export a DataTable to a CSV File
        /// </summary>
        /// <param name="dt"></param>
        /// <param name="filename"></param>
        public static void DataTableToCSVFile(System.Data.DataTable dt, string filename)
        {
            int RecordLimit = 5000;
            try
            {
                if (dt.Rows.Count < RecordLimit)
                {
                    DataTableToCSVFile_InOneString(dt, filename);
                }
                else
                {
                    DataTableToCSVFile_LineByLine(dt, filename);
                }
            }
            catch (System.Exception ex)
            {
                HandleException(ex);
            }
        }

        public static void DataTableToCSVFile_InOneString(DataTable dt, string filename)
        {
            string output = "";

            string field_name_list = "";

            foreach (DataColumn dc in dt.Columns)
            {
                string fieldname = dc.ColumnName.Trim();
                field_name_list = AddItemToList(field_name_list, fieldname);
            }

            output += field_name_list + lb;
            output += dt.Rows.Count.ToString().Trim() + lb;

            //output data
            string value_data = "";
            foreach (DataRow dr in dt.Rows)
            {
                string valuelist = "";
                foreach (DataColumn dc in dt.Columns)
                {
                    string value = ("" + dr[dc.ColumnName]).Trim();
                    valuelist = AddItemToList(valuelist, ProcessValueDataTableToThermo(value));
                }
                value_data += valuelist + lb;
            }

            output += value_data;
            WriteTextFile(filename, output);
        }

        public static void DataTableToCSVFile_LineByLine(DataTable dt, string filename)
        {
            string field_name_list = "";

            System.IO.FileStream fs = new System.IO.FileStream(filename, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.Write);
            System.IO.StreamWriter sw = new System.IO.StreamWriter(fs);

            foreach (DataColumn dc in dt.Columns)
            {
                string fieldname = dc.ColumnName.Trim();
                field_name_list = AddItemToList(field_name_list, fieldname);
            }

            sw.WriteLine(field_name_list);
            sw.WriteLine(dt.Rows.Count.ToString().Trim());

            //output data
            foreach (DataRow dr in dt.Rows)
            {
                string valuelist = "";
                foreach (DataColumn dc in dt.Columns)
                {
                    string value = ("" + dr[dc.ColumnName]).Trim();
                    valuelist = AddItemToList(valuelist, ProcessValueDataTableToThermo(value));
                }

                sw.WriteLine(valuelist);
            }

            sw.Flush();
            sw.Close();
        }

        private static string AddItemToList(string list, string item)
        {
            if (list.Trim() != "")
                list += "," + item;
            else
                list = item;

            return list;
        }

        private static string InsertToList(string list, string value)
        {
            if (String.IsNullOrEmpty(list))
                list = value;
            else
                list += ", " + value;

            return list;
        }

        /// <summary>
        /// add number of spaces to the left of string because Thermo would add number of spaces in front to
        /// round out all the usable spaces in a field. "    49344" instead of "49344"
        /// </summary>
        /// <param name="val"></param>
        /// <param name="num_spaces"></param>
        /// <returns></returns>
        private static string Space(string val, int num_spaces)
        {
            return val.PadLeft(num_spaces);
        }
        #endregion //EO Database

        #region Security
        #region File Checksum
		/// <summary>
		/// Create SHA1 checksum file for a file
		/// </summary>
		/// <param name="inputfile"></param>
		/// <param name="outputfile"></param>
		public static void GenerateSHA1CheckSumFile(string inputfile, string outputfile)
		{
			if (System.IO.File.Exists(inputfile))
			{
				System.Security.Cryptography.SHA1 sha1 = System.Security.Cryptography.SHA1.Create();

				byte[] data = sha1.ComputeHash(ReadFileIntoByteArray(inputfile));

				if (data.Length > 0)
				{
					WriteByteArrayToFile(data, outputfile);
				}
			}
		}

		/// <summary>
		/// calculate SHA1 hash for a file
		/// </summary>
		/// <param name="filename"></param>
		/// <returns>byte array of SHA1 hash</returns>
		public static byte[] CalculateSHA1HashInByteArray(string filename)
		{
			System.Security.Cryptography.SHA1 sha1 = System.Security.Cryptography.SHA1.Create();
			byte[] data = sha1.ComputeHash(ReadFileIntoByteArray(filename));
			return data;
		}

		#endregion //File Checksum
        #region Public Static Functions
        /// <summary>
        /// mask a string using a predefined security key
        /// </summary>
        /// <param name="cleanText"></param>
        /// <returns></returns>
        public static string MaskString(string cleanText)
        {
            string cryptoText = "";
            if (cleanText.Trim() != "")
                cryptoText = EncryptString(cleanText, def.mask_sec_key);

            return cryptoText;
        }

        /// <summary>
        /// unmask a crypto text return it to clear text decrypt using predefinied security key
        /// </summary>
        /// <param name="CryptoText"></param>
        /// <returns></returns>
        public static string UnmaskString(string CryptoText)
        {
            string CleanText = "";
            if (CryptoText.Trim() != "")
                CleanText = DecryptString(CryptoText, def.mask_sec_key);
            return CleanText;
        }
        /// <summary>
        /// Encrypt a plain text to secured string
        /// </summary>
        /// <param name="clearText">Plain Text</param>
        /// <param name="Password">password to encrypt the Plain Text</param>
        /// <returns>masked, Hashed string generated using the password</returns>
        /// <remarks>
        /// Can be call multiple time to generate a more convuluted string
        /// </remarks>
        public static string EncryptString(string clearText, string Password)
        {
            byte[] clearBytes =
                System.Text.Encoding.Unicode.GetBytes(clearText);

            System.Security.Cryptography.PasswordDeriveBytes pdb = new System.Security.Cryptography.PasswordDeriveBytes(Password,
                new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 
							   0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

            byte[] encryptedData = Encrypt(clearBytes,
                pdb.GetBytes(32), pdb.GetBytes(16));
            return System.Convert.ToBase64String(encryptedData);
        }

        /// <summary>
        /// Decrypt a secured string back into plain text
        /// </summary>
        /// <param name="cipherText"></param>
        /// <param name="Password"></param>
        /// <returns></returns>
        public static string DecryptString(string cipherText, string Password)
        {
            byte[] cipherBytes = System.Convert.FromBase64String(cipherText);

            System.Security.Cryptography.PasswordDeriveBytes pdb = new System.Security.Cryptography.PasswordDeriveBytes(Password,
                new byte[] {0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 
							   0x64, 0x76, 0x65, 0x64, 0x65, 0x76});

            byte[] decryptedData = Decrypt(cipherBytes,
                pdb.GetBytes(32), pdb.GetBytes(16));

            return System.Text.Encoding.Unicode.GetString(decryptedData);
        }

        #endregion //Public Static Functions

        #region Private Functions
        private static byte[] Encrypt(byte[] clearData, byte[] Key, byte[] IV)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream();

            System.Security.Cryptography.Rijndael alg = System.Security.Cryptography.Rijndael.Create();

            alg.Key = Key;
            alg.IV = IV;

            System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(ms,
                alg.CreateEncryptor(), System.Security.Cryptography.CryptoStreamMode.Write);

            cs.Write(clearData, 0, clearData.Length);

            cs.Close();

            byte[] encryptedData = ms.ToArray();

            return encryptedData;
        }

        private static byte[] Decrypt(byte[] cipherData,
            byte[] Key, byte[] IV)
        {
            System.IO.MemoryStream ms = new System.IO.MemoryStream();

            System.Security.Cryptography.Rijndael alg = System.Security.Cryptography.Rijndael.Create();

            alg.Key = Key;
            alg.IV = IV;

            System.Security.Cryptography.CryptoStream cs = new System.Security.Cryptography.CryptoStream(ms,
                alg.CreateDecryptor(), System.Security.Cryptography.CryptoStreamMode.Write);

            cs.Write(cipherData, 0, cipherData.Length);

            cs.Close();

            byte[] decryptedData = ms.ToArray();

            return decryptedData;
        }

        #endregion //EO Private functions
        #endregion //EO security

        #region Web Mail
        /// <summary>
        /// Send Email using SMTP
        /// </summary>
        /// <param name="ht">
        /// ht with the following field:
        /// from_email, from_display, to_email, subject, body, attachment, smtp_host
        /// </param>
        public static void SendEmail(string smtphost, string email_from, string email_to, string subject, string bodytext)
        {
            MailMessage msg = new MailMessage();
            msg.From = new MailAddress(email_from);
            msg.To.Add(new MailAddress(email_to));
            msg.Subject = subject;
            msg.Body = bodytext;
            msg.Priority = MailPriority.High;

            SmtpClient smc = new SmtpClient(smtphost);
            smc.Send(msg);
        }
        #endregion //EO Web Mail

        #region XML configuration file
        /// <summary>
        /// reads the xml node and parse them into ht[key] = value in a hash table
        /// </summary>
        /// <param name="ht">Hash Table contains the settings values</param>
        /// <param name="filename">XML configuration file name </param>
        public static void GetSettingHash(System.Collections.Hashtable ht, string filename)
        {
            string ElementTagName = "setting";

            if (File.Exists(filename))
            {
                System.Xml.XmlDocument xdoc = new System.Xml.XmlDocument();
                xdoc.Load(filename);

                if (xdoc != null)
                {
                    System.Xml.XmlNodeList alist = xdoc.GetElementsByTagName(ElementTagName);

                    foreach (System.Xml.XmlElement item in alist)
                    {
                        SetHash(ht, ("" + item.Attributes.GetNamedItem("key").Value).Trim(), ("" + item.Attributes.GetNamedItem("value").Value).Trim());
                    }
                }
            }
        }

        /// <summary>
        /// Read the key, comment pair from XML configuration file
        /// </summary>
        /// <param name="ht">Setting Hash</param>
        /// <param name="filename">xml configuration file</param>
        public static void GetSettingHashComment(System.Collections.Hashtable ht, string filename)
        {
            string ElementTagName = "setting";

            if (File.Exists(filename))
            {
                System.Xml.XmlDocument xdoc = new System.Xml.XmlDocument();
                xdoc.Load(filename);

                if (xdoc != null)
                {
                    System.Xml.XmlNodeList alist = xdoc.GetElementsByTagName(ElementTagName);

                    foreach (System.Xml.XmlElement item in alist)
                    {
                        SetHash(ht, ("" + item.Attributes.GetNamedItem("key").Value).Trim(), ("" + item.Attributes.GetNamedItem("comment").Value).Trim());
                    }
                }
            }

        }

        /// <summary>
        /// save the changed setting hash table to xml config file
        /// </summary>
        /// <param name="filename">xml configuration file name </param>
        /// <param name="ht">hash table that contains the settings</param>
        public static void SaveSettingHash(System.Collections.Hashtable ht, string filename)
        {
            System.Xml.XmlDocument xdoc = new System.Xml.XmlDocument();
            xdoc.Load(filename);

            foreach (object o in ht.Keys)
            {
                string Key = ("" + o.ToString()).Trim();
                string Value = ("" + ht[Key]).Trim();

                SetXml(xdoc, Key, Value);
            }

            xdoc.Save(filename);
        }


        /// <summary>
        /// save the setting hash to a new xml configuration file
        /// </summary>
        /// <param name="ht">Hash contains setting key value pairs</param>
        /// <param name="filename">xml configuration file name</param>
        public static void SaveSettingsHashNew(System.Collections.Hashtable ht, string filename)
        {
            //			<?xml version="1.0" encoding="utf-8" standalone="yes"?>
            //			<appsetting>
            //				<setting key="dbsource" value="DL92" />
            //			</appsetting>

            try
            {
                string ElementTagName = "setting";

                System.Xml.XmlTextWriter xw = new System.Xml.XmlTextWriter(filename, System.Text.Encoding.Default);

                xw.Formatting = System.Xml.Formatting.Indented;

                xw.WriteStartDocument(true);
                //<appsetting>
                xw.WriteStartElement("appsetting");

                foreach (string key in ht.Keys)
                {
                    //<setting
                    xw.WriteStartElement(ElementTagName);

                    string val = ("" + ht[key]).Trim();

                    if (key != "" && val != "")
                    {
                        //key="dbsource"
                        xw.WriteAttributeString("key", key);
                        //value="DL92"
                        xw.WriteAttributeString("value", val);
                    }

                    // />
                    xw.WriteEndElement();
                }

                // </appsettings>
                xw.WriteEndElement();

                xw.WriteEndDocument();

                xw.Close();
            }
            catch (System.Exception)
            {
            }
        }

        /// <summary>
        /// save the setting hash to a new xml configuration file
        /// </summary>
        /// <param name="htComment">hash table contains comments</param>
        /// <param name="htValue">hash table contains key values</param>
        /// <param name="filename">xml configuration file name</param>
        public static void SaveSettingsHashNew(System.Collections.Hashtable htValue, System.Collections.Hashtable htComment, string filename)
        {
            try
            {
                string ElementTagName = "setting";

                System.Xml.XmlTextWriter xw = new System.Xml.XmlTextWriter(filename, System.Text.Encoding.Default);

                xw.Formatting = System.Xml.Formatting.Indented;

                xw.WriteStartDocument(true);
                xw.WriteStartElement("appsetting");

                foreach (string key in htValue.Keys)
                {
                    xw.WriteStartElement(ElementTagName);

                    string val = ("" + htValue[key]).Trim();
                    string note = ("" + htComment[key]).Trim();

                    if (key != "" && val != "")
                    {
                        //key="dbsource"
                        xw.WriteAttributeString("key", key);
                        //value="DL92"
                        xw.WriteAttributeString("value", val);
                        //comment =""
                        xw.WriteAttributeString("comment", note);
                    }

                    xw.WriteEndElement();
                }

                // </appsettings>
                xw.WriteEndElement();

                xw.WriteEndDocument();

                xw.Close();
            }
            catch (System.Exception)
            {
            }
        }

        private static void SetXml(System.Xml.XmlDocument xd, string key, string val)
        {
            string ElementTagName = "setting";

            System.Xml.XmlNodeList aList = xd.GetElementsByTagName(ElementTagName);

            foreach (System.Xml.XmlElement aElement in aList)
            {
                System.Xml.XmlNode keynode = aElement.Attributes.GetNamedItem("key");
                System.Xml.XmlNode valuenode = aElement.Attributes.GetNamedItem("value");
                if (keynode.Value == key)
                {
                    valuenode.Value = val;
                    return;
                }
            }
        }

        private static void SetHash(System.Collections.Hashtable ht, string key, string value)
        {
            if (key != "")
            {
                ht[key] = value;
            }
        }
        #endregion //EO Public Static Functions

        #region CSV Functions
        private static string separator = null;

        //string[] fields = fieldlist.Split(new char[] { ',' });
        public static string[] csv_split(string line, string Separator)
        {
            separator = Separator;
            if (line == null) return null;
            if (line.Length == 0) return new string[0];

            System.Collections.ArrayList res = new System.Collections.ArrayList();
            ParseCsvFields(res, line);

            for (int i = 0; i < res.Count; i++)
            {
                string token = res[i].ToString().Trim();
                if (token.StartsWith(quote) && token.EndsWith(quote))
                {
                    token = token.Replace(quote, "");
                    res[i] = token;
                }
            }

            return (string[])res.ToArray(typeof(string));
        }

        private static void ParseCsvFields(System.Collections.ArrayList result, string data)
        {

            int pos = -1;
            while (pos < data.Length)
                result.Add(ParseCsvField(data, ref pos));
        }

        // Parses the field at the given position of the data, modified pos to match
        // the first unparsed position and returns the parsed field
        private static string ParseCsvField(string data, ref int startSeparatorPosition)
        {

            if (startSeparatorPosition == data.Length - 1)
            {
                startSeparatorPosition++;
                // The last field is empty
                return "";
            }

            int fromPos = startSeparatorPosition + 1;

            // Determine if this is a quoted field
            if (data[fromPos] == '"')
            {
                // If we're at the end of the string, let's consider this a field that
                // only contains the quote
                if (fromPos == data.Length - 1)
                {
                    fromPos++;
                    return "\"";
                }

                // Otherwise, return a string of appropriate length with double quotes collapsed
                // Note that FSQ returns data.Length if no single quote was found
                int nextSingleQuote = FindSingleQuote(data, fromPos + 1);
                startSeparatorPosition = nextSingleQuote + 1;
                return data.Substring(fromPos + 1, nextSingleQuote - fromPos - 1).Replace("\"\"", "\"");
            }

            // The field ends in the next separator or EOL
            int nextSeparator = data.IndexOf(separator, fromPos);
            if (nextSeparator == -1)
            {
                startSeparatorPosition = data.Length;
                return data.Substring(fromPos);
            }
            else
            {
                startSeparatorPosition = nextSeparator;
                return data.Substring(fromPos, nextSeparator - fromPos);
            }
        }

        // Returns the index of the next single quote mark in the string 
        // (starting from startFrom)
        private static int FindSingleQuote(string data, int startFrom)
        {

            int i = startFrom - 1;
            while (++i < data.Length)
                if (data[i] == '"')
                {
                    // If this is a double quote, bypass the chars
                    if (i < data.Length - 1 && data[i + 1] == '"')
                    {
                        i++;
                        continue;
                    }
                    else
                        return i;
                }
            // If no quote found, return the end value of i (data.Length)
            return i;
        }
        #endregion

        #region Private functions
        private static void HandleException(System.Exception ex)
        {
            System.Diagnostics.Debug.Write(ex.Message);
        }
        #endregion
    }
}
